<?php

/**
 * XunLianPay
 */

namespace app\api\service\payment;

use app\api\service\ApiPayment;
use app\common\library\exception\OrderException;

class XunLianPay extends ApiPayment
{
    public function alipay($order)
    {
        return $this->requestApi($order, 'ALP');
    }

    public function wxpayH5($order)
    {
        return $this->requestH5Api($order, 'WXP');
    }

    public function wxpay($order)
    {
        return $this->requestApi($order, 'WXP');
    }

    //生成签名
    private function sign($param)
    {
        $str = "";
        if ($param) {
            ksort($param);
            foreach ($param as $k => $v) {
                if ($k != "sign" && $v != "") {
                    $str .= $k . "=" . $v . "&";
                }
            }
            $str = trim($str, "&") . $this->config['signKey'];
        }

        $sign = hash($this->config['signType'], $str);

        return $sign;
    }

    //发送post请求到服务器
    private function postData($url, $params)
    {
        $jsonData = json_encode($params);

        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            array(
                "Content-Type: application/json; charset=utf-8",
                "Content-Length: " . strlen($jsonData)
            )
        );

        $res = curl_exec($curl);
        // curl失败
        if (0 !== curl_errno($curl)) {
            print_r(curl_error($curl));
            curl_close($curl);

            return false;
        }
        // curl成功
        curl_close($curl);

        return $res;
    }

    private function requestH5Api($order, $type)
    {
        $frontUrl = $order['return_url'] ?? "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}/success"; //支付成功后跳转的界面

        $this->config['url'] = "https://showmoney.cn/scanpay/v2h5";
        $txamt = $order['amount'];
        $reqDatas = array(
            "version" => '2.3.1', //版本号
            "signType" => $this->config['signType'],   //签名方式
            "charset" => "utf-8", //编码格式
            "orderNum" => $order['trade_no'],    //订单号
            "busicd" => "WPAY",   //交易类型
            "chcd" => $type,  //渠道: ALP 支付宝, WXP 微信 
            "mchntid" => $this->config['mchntid'],  //商户号
            "terminalid" => $this->config['terminalid'],    //终端号
            "txamt" => str_pad(bcmul($txamt, 100, 0), 12, "0", STR_PAD_LEFT),    //订单金额: 单位为分，左补 0 至补齐 12 位，例如 000000000001 表示 1 分，000000000100 表 示 1 元。 
            "attach" => $order['subject'],
            "frontUrl" => $frontUrl,
            "backUrl" => "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}/notify/XunLianPay",
            // "timeStart" => date("YmdHis"),
            // "timeExpire" => date("YmdHis", time() + 3600),
        );

        $params = array_filter($reqDatas); //去除空值，空值不参与签名
        $reqSignStr = $this->sign($reqDatas);
        $params["sign"] = $reqSignStr;

        // $resDataStr = $this->postData($this->config['url'], $reqDatas);
        $url = $this->config['url'] . '?data=' . base64_encode(json_encode($params));

        return [
            'order_id' => $order['out_trade_no'],
            'pay_seq' => $order['trade_no'],
            'pay_url' => $url,
            'pay_app_url' => $url
        ];
    }

    private function requestApi($order, $type)
    {
        $this->config['url'] = "https://showmoney.cn/scanpay/unified";
        $txamt = $order['amount'];
        $reqDatas = array(
            "version" => $this->config['version'], //版本号
            "signType" => $this->config['signType'],   //签名方式
            "charset" => "utf-8", //编码格式
            "orderNum" => $order['trade_no'],    //订单号
            "txndir" => "Q",  //交易方向
            "busicd" => "PAUT",   //交易类型
            "inscd" => $this->config['inscd'],  //机构号
            "chcd" => $type,  //渠道: ALP 支付宝, WXP 微信 
            "mchntid" => $this->config['mchntid'],  //商户号
            "terminalid" => $this->config['terminalid'],    //终端号
            "txamt" => str_pad(bcmul($txamt, 100, 0), 12, "0", STR_PAD_LEFT),    //订单金额: 单位为分，左补 0 至补齐 12 位，例如 000000000001 表示 1 分，000000000100 表 示 1 元。 
            "frontUrl" => "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}/success", //支付成功后跳转的界面
            "backUrl" => "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}/notify/XunLianPay",
            "attach" => $order['subject'],
        );

        $params = array_filter($reqDatas); //去除空值，空值不参与签名
        $reqSignStr = $this->sign($reqDatas);
        $reqDatas["sign"] = $reqSignStr;

        $resDataStr = $this->postData($this->config['url'], $reqDatas);

        $resDatas = json_decode($resDataStr, true);

        //返回数据处理代码
        if ($resDatas && $resDatas["sign"]) {
            $resSignStr = $this->sign($resDatas);
            if ($resSignStr  == $resDatas["sign"]) {
                $respcd = $resDatas["respcd"]; //应答码, 对比应答码列表做处理;
                if ($respcd == "09") { //待支付
                    $fileUrl = $this->makeQRimg($resDatas["qrcode"]);
                    return [
                        'order_id' => $order['out_trade_no'],
                        'pay_seq' => $order['trade_no'],
                        'pay_url' => $fileUrl,
                        'pay_app_url' => $resDatas["qrcode"]
                    ];
                }
            }
        }

        throw new OrderException([
            'msg' => $resDatas["errorDetail"],
            'errCode' => 555,
        ]);
    }

    private function makeQRimg($url)
    {
        $fileName = date('Ymd') . DS . date('His') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT) . '.png';
        if (!file_exists(UPLOAD_PATH . 'qr')) {
            mkdir(UPLOAD_PATH . 'qr', 0777, true);
        }

        if (!file_exists(UPLOAD_PATH . 'qr' . DS . date('Ymd'))) {
            mkdir(UPLOAD_PATH . 'qr' . DS . date('Ymd'), 0777, true);
        }

        $renderer = new \BaconQrCode\Renderer\Image\Png();
        $renderer->setHeight(256);
        $renderer->setWidth(256);
        $writer = new \BaconQrCode\Writer($renderer);
        $writer->writeFile($url, UPLOAD_PATH . DS . 'qr/' . $fileName);

        return UPLOAD_URL . 'qr/' . $fileName;
    }


    public function notify()
    {
        return $this->verifyOrderNotify();
    }

    /**
     * 回调验签.
     *
     *
     * @return array
     *
     * @throws OrderException
     */
    private function verifyOrderNotify()
    {
        file_put_contents("/tmp/XunLianPay.log", var_export($_GET, true), FILE_APPEND);
        parse_str(urldecode($_SERVER['QUERY_STRING']), $queryParam);
        if ($queryParam['respcd'] == "00") {
            return array(
                'trade_no' => $queryParam['orderNum'],
            );
        }
        return false;
    }
}
